#include<iostream>
#include<string>
#include<vector>
#include<sstream>
#include<fstream>

const std::string HttpSpe="\r\n";
const std::string path="./wwwroot";
const std::string homepage="intax.html";
const std::string BlankSep=" ";

class HttpRequest//请求
{

public:
    HttpRequest():_path(path){}
    bool Getline(std::string& request,std::string* line)
    {
        int pos=request.find(HttpSpe);
        if(pos==std::string::npos)return false;
        *line=request.substr(0,pos);
        request.erase(0,pos+HttpSpe.size());//删除一行数据
        return true;
    }
    void Deserialize(std::string& request)
    {
        std::string line;
        bool ok=Getline(request,&line);
        if(!ok)return;
        _request_line=line;
        while(true)
        {
            ok=Getline(request,&line);
            if(ok&&line.empty())
            {
                _request_contents=request;
                break;
            }
            else if(ok)
            {
                _request_header.push_back(line);
            }
            else
            {
                break;
            }
        }
        _blank=HttpSpe;
    }

    void PraseHttpLine()
    {
        std::stringstream ss(_request_line);
        ss>>_method>>_url>>_http_version;
        if(_url=="/")
        {
            _path+=_url;
            _path+=homepage;
        }
        else
        {
            _path+=_url;
        }
    }

    void PraseSuffix()//wwwroot/image/1.jpg
    {
        auto pos=_path.rfind(".");
        if(pos==std::string::npos)_http_suffix=".html";
        else _http_suffix=_path.substr(pos);
    }

    void Parse()
    {
        // 1.分析请求行
        PraseHttpLine();
        // 2.提取后缀
        PraseSuffix();
    }

    std::string GetFileContentHelper(const std::string& path)
    {
        // std::fstream file(path,std::ios::binary);
        // if(!file.is_open())return "";
        // std::string content;
        // std::string line;
        // while(std::getline(file,line))
        // {
        //     content+=line;
        // }
        // file.close();
        // return content;

        std::ifstream in(path, std::ios::binary);
        if (!in.is_open())
            return "";
        in.seekg(0, in.end);       // 将文件读取指针移动到文件末尾
        int filesize = in.tellg(); // 获取当前位置（即文件大小）
        in.seekg(0, in.beg);       // 将文件读取指针重置回文件开头，以便从头开始读取文件内容

        // 两种写法：
        std::string content;
        content.resize(filesize);
        in.read((char *)content.c_str(), filesize);

        // std::vector<char> content(filesize);
        // in.read((char*)content.data(),filesize);

        in.close();
        return content;
    }


    std::string GetFileContent()
    {
        return GetFileContentHelper(_path);
    }

    std::string Get404()
    {
        return GetFileContentHelper("./wwwroot/404.html");
    }

    std::string& GetUrl()
    {
        return _url;
    }
    std::string& GetPath()
    {
        return _path;
    }
    std::string& GetSuffix()
    {
        return _http_suffix;
    }
    void Dubug()
    {
        std::cout<<"请求行: "<<_request_line<<std::endl;
        for(auto& e:_request_header)
        {
            std::cout<<"--->"<<e<<std::endl;
        }
        std::cout<<"_blank: "<<_blank<<std::endl;
        std::cout<<"_request_contents: "<<_request_contents<<std::endl;

        
        std::cout<<"_method: "<<_method<<std::endl;
        std::cout<<"_url: "<<_url<<std::endl;
        std::cout<<"_http_version: "<<_http_version<<std::endl;
    }

    ~HttpRequest(){}
private:
    std::string _request_line;//请求行
    std::vector<std::string> _request_header;//请求报头
    std::string _blank;//空行
    std::string _request_contents;//请求参数(有效载荷)

    
    std::string _method;//请求行的请求方法
    std::string _url;//路径
    std::string _http_version;//版本

    std::string _path;
    std::string _http_suffix;
};



class HttpResponse
{
public:
    HttpResponse():_http_version("HTTP/1.0"),_code(200),_code_desc("OK"),_blank(HttpSpe)
    {}

    void MakeStatueLine()
    {
        _response_line=_http_version+BlankSep+std::to_string(_code)+BlankSep+_code_desc+HttpSpe;
    }

    void AddHeader(const std::string& header)
    {
        _response_header.push_back(header);
    }

    void AddContent(const std::string& content)
    {
        _response_contents=content;
    }
    std::string Serialize()//序列化
    {
        std::string httpresponse=_response_line;
        for(auto& header:_response_header)
        {
            httpresponse+=header;
        }
        httpresponse+=HttpSpe;
        httpresponse+=_response_contents;
        return httpresponse;
    }

    void SetCode(int code)
    {
        _code=code;
    } 

    void SetCodeDesc(const std::string& CodeDesc)
    {
        _code_desc=CodeDesc;
    }

    ~HttpResponse(){}
private:
    std::string _response_line;//响应行
    std::vector<std::string> _response_header;//响应报头
    std::string _blank;//空行
    std::string _response_contents;

    std::string _http_version;//版本
    int _code;//状态码
    std::string _code_desc;//状态码描述    
};